package com.dlc.shop.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huifu.bspay.sdk.opps.core.request.V2UserBasicdataEntRequest;
import com.huifu.bspay.sdk.opps.core.request.V2UserBasicdataIndvRequest;
import com.huifu.bspay.sdk.opps.core.request.V2UserBusiOpenRequest;
import com.huifu.bspay.sdk.opps.core.utils.DateTools;
import com.huifu.bspay.sdk.opps.core.utils.SequenceTools;
import com.dlc.shop.bean.model.Huifu;
import com.dlc.shop.bean.model.ShopBankCard;
import com.dlc.shop.bean.model.ShopCompany;
import com.dlc.shop.bean.model.ShopDetail;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.config.ShopConfig;
import com.dlc.shop.dao.HuifuMapper;
import com.dlc.shop.huifu.DemoTestConstants;
import com.dlc.shop.huifu.OppsMerchantConfigDemo;
import com.dlc.shop.service.HuifuService;
import com.dlc.shop.service.OrderService;
import com.dlc.shop.service.ShopBankCardService;
import com.dlc.shop.service.ShopCompanyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.dlc.shop.huifu.BaseCommonDemo.doExecute;
import static com.dlc.shop.huifu.BaseCommonDemo.doInit;


/**
 * @author lgh on 2018/09/15.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HuifuServiceImpl extends ServiceImpl<HuifuMapper, Huifu> implements HuifuService {

    private final ShopCompanyService companyService;
    private final ShopBankCardService shopBankCardService;
    private final ShopConfig shopConfig;

    @Override
    public Map<String, Object> huifuOpen(ShopDetail shopDetail) throws Exception {

        ShopCompany shopCompany = new ShopCompany();
        List<ShopCompany> shopCompanies  = companyService.list(new LambdaQueryWrapper<ShopCompany>().eq(ShopCompany::getShopId,
                shopDetail.getShopId()));

        if (shopCompanies.size() > 1){
            throw new YamiShopBindException("请审核完成后再开户！");
        }
        shopCompany = shopCompanies.get(0);

        if(shopCompany == null){
            throw new RuntimeException("店铺未绑定企业信息");
        }

        // 1. 数据初始化
        doInit(OppsMerchantConfigDemo.getMerchantConfig());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        // 2.组装请求参数
        V2UserBasicdataEntRequest request = new V2UserBasicdataEntRequest();
        // 请求流水号
        request.setReqSeqId(SequenceTools.getReqSeqId32());
        // 请求日期
        request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
        // 企业用户名称
        request.setRegName(shopCompany.getFirmName());
        // 营业执照编号
        request.setLicenseCode(shopCompany.getCreditCode());
        // 证照有效期类型
        request.setLicenseValidityType("1");
        // 证照有效期起始日期
        if (shopCompany.getStartTime() == null){
            throw new YamiShopBindException("请填写营业期限！");
        }
        if (shopCompany.getResidence() == null){
            throw new YamiShopBindException("请填写营业住所/注册地址！");
        }
        if (shopCompany.getCardStartTime() == null){
            throw new YamiShopBindException("请设置法人身份证有效期限开始时间！");
        }
        request.setLicenseBeginDate(sdf.format(shopCompany.getStartTime()));
        // 证照有效期结束日期日期格式：yyyyMMdd; 非长期有效时必填；&lt;font color&#x3D;&quot;green&quot;&gt;示例值：20320905&lt;/font&gt;
//        request.setLicenseEndDate("20400117");
        // 注册地址(省)
        request.setRegProvId("310000");
        // 注册地址(市)
        request.setRegAreaId("310100");
        // 注册地址(区)
        request.setRegDistrictId("310104");
        // 注册地址(详细信息)
        request.setRegDetail(shopCompany.getResidence());
        // 法人姓名
        request.setLegalName(shopCompany.getRepresentative());
        // 法人证件类型
        request.setLegalCertType("00");
        // 法人证件号码
        request.setLegalCertNo(shopCompany.getIdCard());
        // 法人证件有效期类型
        request.setLegalCertValidityType("1");
        // 法人证件有效期开始日期
        request.setLegalCertBeginDate(sdf.format(shopCompany.getCardStartTime()));
        // 联系人姓名
        request.setContactName(shopCompany.getRepresentative());
        // 联系人手机号
        request.setContactMobile(shopDetail.getTel());

        // 设置非必填字段
        Map<String, Object> extendInfoMap = new HashMap<>();
        extendInfoMap.put("login_name",shopDetail.getTel());
        request.setExtendInfo(extendInfoMap);
        log.info("参数json:" + JSONObject.toJSONString(request));
        // 3. 发起API调用
        Map<String, Object> response = doExecute(request);
        log.info("个人用户基本信息开户返回数据:" + JSONObject.toJSONString(response));
        return response;
    }

    public Map<String, Object> huifuBind(ShopDetail shopDetail) throws Exception  {

        ShopBankCard shopBankCard = shopBankCardService.
                getOne(new LambdaQueryWrapper<ShopBankCard>().
                        eq(ShopBankCard::getShopId, shopDetail.getShopId()).
                        eq(ShopBankCard::getStatus, 1).
                        eq(ShopBankCard::getIsDefault,1));
       if (Objects.isNull(shopBankCard)){
           log.info("银行信息为空");
           throw new YamiShopBindException("请设置一个默认卡！");
       }
        ShopCompany shopCompany = new ShopCompany();
       List<ShopCompany> shopCompanies  = companyService.list(new LambdaQueryWrapper<ShopCompany>().eq(ShopCompany::getShopId,
                shopDetail.getShopId()));
       if (shopCompanies.size() > 1){
           throw new YamiShopBindException("请审核完成后再绑定！");
       }
         shopCompany = shopCompanies.get(0);
        // 1. 数据初始化
        doInit(OppsMerchantConfigDemo.getMerchantConfig());

        // 2.组装请求参数
        V2UserBusiOpenRequest request = new V2UserBusiOpenRequest();
        // 汇付ID
        request.setHuifuId(shopDetail.getHuifuId());
        // 请求流水号
        request.setReqSeqId(SequenceTools.getReqSeqId32());
        // 请求日期
        request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
        // 渠道商/商户汇付Id
        request.setUpperHuifuId(DemoTestConstants.DEMO_SYS_ID);

        // 设置非必填字段
        Map<String, Object> extendInfoMap = getExtendInfos(shopBankCard,shopCompany);
        request.setExtendInfo(extendInfoMap);
        log.info("绑定开户发送数据:" + JSONObject.toJSONString(request));

        // 3. 发起API调用
        Map<String, Object> response = doExecute(request);
        log.info("绑定开户返回数据:" + JSONObject.toJSONString(response));

        return response;
    }

    /**
     * 非必填字段
     * @return
     */
    private Map<String, Object> getExtendInfos(ShopBankCard shopBankCard,ShopCompany shopCompany) {
        // 设置非必填字段
        Map<String, Object> extendInfoMap = new HashMap<>();
        // 结算信息配置
        extendInfoMap.put("settle_config", getSettleConfig(shopBankCard));
        // 结算卡信息
        extendInfoMap.put("card_info", getCardInfo(shopBankCard,shopCompany));
        // 取现配置列表
        extendInfoMap.put("cash_config", getCashConfig());
        // 文件列表
        //extendInfoMap.put("file_list", getFileList());
        // 延迟入账开关
        // extendInfoMap.put("delay_flag", "");
        // 斗拱e账户功能配置
        // extendInfoMap.put("elec_acct_config", getElecAcctConfig());
        // 灵活用工开关
        // extendInfoMap.put("open_tax_flag", "");
        // 异步请求地址
        extendInfoMap.put("async_return_url", shopConfig.getDomain().getPlatformDomainName()+"/shop/huifu/callback");
        return extendInfoMap;
    }

    private static String getSettleConfig(ShopBankCard shopBankCard) {
        JSONObject dto = new JSONObject();
        // 结算周期
        dto.put("settle_cycle", "T1");
        // 起结金额
        dto.put("min_amt", "0.01");
        // 留存金额
        dto.put("remained_amt", "0.01");
        // 结算摘要
        //dto.put("settle_abstract", "结算摘要");
        // 手续费外扣标记
        dto.put("out_settle_flag", "2");
        // 结算手续费外扣时的汇付ID外扣手续费承担方的汇付ID。外扣时必填；&lt;font color&#x3D;&quot;green&quot;&gt;示例值：6666000123123123&lt;/font&gt;
        //dto.put("out_settle_huifuid", DemoTestConstants.DEMO_SYS_ID);
        // 结算手续费外扣时的账户类型外扣手续费账户类型； 01：基本户（为空时默认值）， 05：充值户；外扣时必填；&lt;br/&gt;&lt;font color&#x3D;&quot;green&quot;&gt;示例值：01&lt;/font&gt;
        //dto.put("out_settle_acct_type", "01");
        // 结算方式
        dto.put("settle_pattern", "P1");
        // 结算批次号settle_pattern为P0时必填；[参见结算批次说明](https://paas.huifu.com/partners/api/#/csfl/api_csfl_jspc)
        //dto.put("settle_batch_no", "300");
        // 是否优先到账settle_pattern为P0时选填， Y：是 N：否（为空默认取值）；&lt;font color&#x3D;&quot;green&quot;&gt;示例值：Y&lt;/font&gt;
        //dto.put("is_priority_receipt", "P1");
        // 自定义结算处理时间settle_pattern为P1时必填，注意：00:00到00:30不能指定；格式：HHmmss；&lt;font color&#x3D;&quot;green&quot;&gt;示例值：103000&lt;/font&gt;
        dto.put("settle_time", "183000");
        // 节假日结算手续费率settle_cycle为D1时必填。单位%，需保留小数点后两位。取值范围[0.00，100.00]，不收费请填写0.00；settle_cycle&#x3D;T1时，不生效 ；settle_cycle为D1时，遇节假日按此费率结算 ；&lt;font color&#x3D;&quot;green&quot;&gt;示例值：0.05&lt;/font&gt;
        //dto.put("fixed_ratio", "0.00");
        // 工作日结算手续费率
        // dto.put("workday_fixed_ratio", "");
        // 工作日结算手续费固定金额
        // dto.put("workday_constant_amt", "");
        return dto.toJSONString();
    }

    private static String getCardInfo(ShopBankCard shopBankCard,ShopCompany shopCompany) {
        log.info("结算卡信息为:" +shopBankCard.toString());
        if (shopBankCard.getBankCardPro() == null){
            throw new YamiShopBindException("请设置一个卡类型为对公还是对私！");
        }
        if (shopCompany.getIdCard() == null){
            throw new YamiShopBindException("请填写法人身份证编号！");
        }
        if (shopCompany.getCardStartTime() == null){
            throw new YamiShopBindException("请设置法人身份证有效期限开始时间！");
        }
        JSONObject dto = new JSONObject();
        // 卡类型
        dto.put("card_type", shopBankCard.getBankCardPro()==0 ? "1" : "0");
        // 卡户名
        dto.put("card_name", shopBankCard.getRecipientName());
        // 卡号
        dto.put("card_no", shopBankCard.getCardNo());
        // 银行所在省
        dto.put("prov_id", shopBankCard.getProvinceCode());
        // 银行所在市
        dto.put("area_id", shopBankCard.getCityCode());
        if(shopBankCard.getBankCardPro() == 1){
            // 银行号当card_type=0时必填，对私可以为空;
            dto.put("bank_code", shopBankCard.getBankCode());
            // 支行联行号当card_type=0时必填;
            dto.put("branch_code", shopBankCard.getBranchCode());
        } else {
            // 持卡人证件类型对私必填   暂时不填
            //dto.put("cert_type", "00");
            // 持卡人证件号码对私必填
            dto.put("cert_no", shopCompany.getIdCard());
            // 持卡人证件有效期类型对私必填；1：长期有效；0：非长期有效
            dto.put("cert_validity_type", "1");
            // 持卡人证件有效期（起始）对私必填；日期格式：yyyyMMdd
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            dto.put("cert_begin_date", sdf.format(shopCompany.getCardStartTime()));
            // 持卡人证件有效期（截止）当cert_validity_type=0时必须填写
            //dto.put("cert_end_date", "20410806");
        }
        // 银行卡绑定手机号
        //dto.put("mp", "15556622368");
        // 默认结算卡标志
        dto.put("is_settle_default", "Y");
        return dto.toJSONString();
    }

    private static String getCashConfig() {
        JSONObject dto = new JSONObject();
        // 提现手续费（固定/元）fix_amt与fee_rate至少填写一项， 需保留小数点后两位，不收费请填写0.00；&lt;font color&#x3D;&quot;green&quot;&gt;示例值：1.00&lt;/font&gt;注：当cash_type&#x3D;D1时为节假日取现手续费
        dto.put("fix_amt", "0.00");
        // 提现手续费率（%）fix_amt与fee_rate至少填写一项，需保留小数点后两位，取值范围[0.00,100.00]，不收费请填写0.00；&lt;font color&#x3D;&quot;green&quot;&gt;示例值：0.05&lt;/font&gt;注：1、如果fix_amt与fee_rate都填写了则手续费&#x3D;fix_amt+支付金额\*fee_rate2、当cash_type&#x3D;D1时为节假日取现手续费
        dto.put("fee_rate", "0.00");
        // D1工作日取现手续费固定金额单位元，需保留小数点后两位。不收费请填写0.00；&lt;font color&#x3D;&quot;green&quot;&gt;示例值：1.00&lt;/font&gt;cash_type&#x3D;D1时，不生效 ；cash_type取现类型为D1时，遇工作日按此费率结算，若未配置则默认按照节假日手续费计算
        // dto.put("weekday_fix_amt", "test");
        // D1工作日取现手续费率单位%，需保留小数点后两位。取值范围[0.00，100.00]，不收费请填写0.00；&lt;font color&#x3D;&quot;green&quot;&gt;示例值：0.05&lt;/font&gt;cash_type&#x3D;D1时，不生效 ；cash_type取现类型为D1时，遇工作日按此费率结算 ，若未配置则默认按照节假日手续费计算
        // dto.put("weekday_fee_rate", "test");
        // 业务类型
        dto.put("cash_type", "T1");
        // 是否交易手续费外扣
        dto.put("out_fee_flag", "2");
        // 手续费承担方
        //dto.put("out_fee_huifu_id", DemoTestConstants.DEMO_SYS_ID);
        // 交易手续费外扣的账户类型
        //dto.put("out_fee_acct_type", "01");
        // 是否优先到账
        // dto.put("is_priority_receipt", "");

        JSONArray dtoList = new JSONArray();
        dtoList.add(dto);
        return dtoList.toJSONString();
    }

}
